package cn.stylefeng.roses.kernel.conversion.service;

import cn.hutool.core.io.IoUtil;
import cn.stylefeng.roses.kernel.conversion.exception.DocumentParseExceptionEnum;
import cn.stylefeng.roses.kernel.conversion.util.DocUtil;
import cn.stylefeng.roses.kernel.conversion.util.ExcelUtil;
import cn.stylefeng.roses.kernel.conversion.util.OfficeFileTypeUtil;
import cn.stylefeng.roses.kernel.conversion.util.PptUtil;
import cn.stylefeng.roses.kernel.file.api.FileInfoApi;
import cn.stylefeng.roses.kernel.file.api.FileOperatorApi;
import cn.stylefeng.roses.kernel.file.api.exception.FileException;
import cn.stylefeng.roses.kernel.file.api.exception.enums.FileExceptionEnum;
import cn.stylefeng.roses.kernel.file.api.pojo.response.SysFileInfoResponse;
import cn.stylefeng.roses.kernel.file.api.util.PdfFileTypeUtil;
import cn.stylefeng.roses.kernel.file.api.util.PicFileTypeUtil;
import cn.stylefeng.roses.kernel.file.api.util.SvgFileTypeUtil;
import cn.stylefeng.roses.kernel.rule.exception.base.ServiceException;
import cn.stylefeng.roses.kernel.rule.util.HttpServletUtil;
import cn.stylefeng.roses.kernel.rule.util.ResponseRenderUtil;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 文档预览的业务
 *
 * @author fengshuonan
 * @since 2023/10/20 22:22
 */
@Service
public class DocumentPreviewService {

    @Resource
    private FileInfoApi fileInfoApi;

    @Resource
    private FileOperatorApi fileOperatorApi;

    /**
     * 根据文件id预览文件
     *
     * @author fengshuonan
     * @since 2023/10/20 22:22
     */
    public void documentPreview(Long fileId) {

        // 获取文件信息
        SysFileInfoResponse fileInfo = fileInfoApi.getFileInfoWithoutContent(fileId);

        // 获取文件的的后缀名
        String fileSuffix = fileInfo.getFileSuffix().toLowerCase();

        // 判断文件不是图片，不是pdf，不是svg，不是office文档，则抛出异常
        if (!PicFileTypeUtil.getFileImgTypeFlag(fileSuffix) && !PdfFileTypeUtil.getFilePdfTypeFlag(
                fileSuffix) && !SvgFileTypeUtil.getFileSvgTypeFlag(fileSuffix) && !OfficeFileTypeUtil.getFileOfficeTypeFlag(fileSuffix)) {
            throw new FileException(FileExceptionEnum.PREVIEW_ERROR_NOT_SUPPORT);
        }

        // 如果是图片，直接渲染
        HttpServletResponse response = HttpServletUtil.getResponse();
        if (PicFileTypeUtil.getFileImgTypeFlag(fileSuffix)) {
            ResponseRenderUtil.setRenderImageHeader(response);
            directRenderFile(fileInfo);
        }

        // 如果是pdf，直接渲染
        else if (PdfFileTypeUtil.getFilePdfTypeFlag(fileSuffix)) {
            response.setContentType(MediaType.APPLICATION_PDF_VALUE);
            directRenderFile(fileInfo);
        }

        // 如果是svg，直接渲染
        else if (SvgFileTypeUtil.getFileSvgTypeFlag(fileSuffix)) {
            response.setContentType(SvgFileTypeUtil.SVG_RESPONSE_CONTENT_TYPE);
            directRenderFile(fileInfo);
        }

        // 如果是Office类型，则按文档预览方式
        else {
            renderOffice(fileInfo);
        }

    }

    /**
     * 直接渲染文件流
     *
     * @author fengshuonan
     * @since 2023/10/20 22:29
     */
    public void directRenderFile(SysFileInfoResponse fileInfo) {

        HttpServletResponse response = HttpServletUtil.getResponse();

        // 获取文件流
        byte[] fileContent = fileOperatorApi.getFileBytes(fileInfo.getFileBucket(), fileInfo.getFileObjectName());

        // 渲染文件流
        ServletOutputStream outputStream = null;

        try {
            outputStream = response.getOutputStream();
        } catch (IOException e) {
            throw new ServiceException(DocumentParseExceptionEnum.EXCEPTION_FILE_IO_ERROR);
        } finally {
            IoUtil.close(outputStream);
        }

        IoUtil.write(outputStream, true, fileContent);
    }


    /**
     * 渲染office
     *
     * @author fengshuonan
     * @since 2023/5/9 21:04
     */
    public void renderOffice(SysFileInfoResponse fileInfo) {

        HttpServletResponse response = HttpServletUtil.getResponse();

        String fileSuffix = fileInfo.getFileSuffix().toLowerCase();

        // 设置响应头
        response.setHeader("Content-Disposition",
                "inline;fileName=" + fileInfo.getFileOriginName() + ";fileName*=UTF-8''" + fileInfo.getFileOriginName());

        // 设置pdf响应content-type
        response.setContentType(MediaType.APPLICATION_PDF_VALUE);

        // 获取到文件的内容
        byte[] fileContent = fileOperatorApi.getFileBytes(fileInfo.getFileBucket(), fileInfo.getFileObjectName());

        try {

            // 如果是word文件
            if (fileSuffix.contains("doc") || fileSuffix.contains("docx")) {
                DocUtil.toPdfByBytes(fileContent, fileSuffix, response.getOutputStream());
            }

            // 如果excel文件
            else if (fileSuffix.contains("xls") || fileSuffix.contains("xlsx")) {
                ExcelUtil.toPdfByBytes(fileContent, response.getOutputStream());
            }

            // 如果ppt文件
            else if (fileSuffix.contains("ppt") || fileSuffix.contains("pptx")) {
                PptUtil.toPdfByBytes(fileContent, fileSuffix, response.getOutputStream());
            }


        } catch (Exception e) {
            throw new ServiceException(DocumentParseExceptionEnum.EXCEPTION_FILE_IO_ERROR);
        }

    }


}
